﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Sfs2X;
using Sfs2X.Core;
using Sfs2X.Entities;
using Sfs2X.Requests;
using Sfs2X.Logging;
using Sfs2X.Requests.MMO;
using Sfs2X.Entities.Data;

public class NetworkController : MonoBehaviour
{

    /// <summary>
    /// Server config info
    /// </summary>
    ServerDefine serverInfo;

    /// <summary>
    /// Server connect variables
    /// </summary>
    private SmartFox sfConnectObj;
    private SmartFoxState sfConnectState = SmartFoxState.Offline;
    private string userName;
    private string password;

    private string loginError;
    private string sfStatus;

    void Awake()
    {
        Application.runInBackground = true;


    }


    // Use this for initialization
    void Start()
    {
        //if (Application.isWebPlayer || Application.isEditor)
        //{
        //    if (!Security.PrefetchSocketPolicy(ServerDefine.SERVER_NAME, ServerDefine.SERVER_PORT, 500))
        //    {
        //        Debug.LogError("Security Exception. Policy file loading failed!");
        //    }
        //}

        CreateConnectObject();
    }

    void FixedUpdate()
    {
        sfConnectObj.ProcessEvents();
    }

    void AttempToConnect(string server_name, int port)
    {
        sfConnectObj.Connect(ServerDefine.SERVER_NAME, ServerDefine.SERVER_PORT);
    }

    void CreateConnectObject()
    {
        // Create connect object
        if (SmartFoxConnection.IsInitialized)
        {
            sfConnectObj = SmartFoxConnection.Connection;
        }
        else
        {
            sfConnectObj = new SmartFox(true);
        }
        Debug.LogWarning("API Version: " + sfConnectObj.Version);

        // Register callback delegate
        sfConnectObj.AddEventListener(SFSEvent.CONNECTION, OnConnection);
        sfConnectObj.AddEventListener(SFSEvent.CONNECTION_LOST, OnConnectionLost);
        sfConnectObj.AddEventListener(SFSEvent.LOGIN, OnLogin);
        sfConnectObj.AddEventListener(SFSEvent.LOGIN_ERROR, OnLoginError);
        sfConnectObj.AddEventListener(SFSEvent.LOGOUT, OnLogout);
    }



    #region HandleConnectEvent

    void OnConnection(BaseEvent evt)
    {
        Debug.Log("OnConnection event");
        bool success = (bool)evt.Params[MySFSParams.PARAM_SUCCESS];
        string error = (string)evt.Params[MySFSParams.PARAM_ERR_MGS];

        Debug.Log("On Connection callback got: " + success + " (error : <" + error + ">)");

        if (success)
        {
            sfConnectState = SmartFoxState.Connected;
            SmartFoxConnection.Connection = sfConnectObj;

            sfStatus = "Connection successful!";
            Debug.Log("TV.Vinh Connection successful!");
        }
        else
        {
            sfStatus = "Can't connect to server!";
            Debug.Log("TV.Vinh Can't connect to server!");
        }
    }

    void OnConnectionLost(BaseEvent evt)
    {


        sfStatus = "Connection was lost, Reason: " + (string)evt.Params[MySFSParams.PARAM_REASON];
    }

    void OnLogin(BaseEvent evt)
    {
        // In v1, userName = deviceName
        // in case username conflict, we random a name for user
        //userName = SystemInfo.deviceName;

        Debug.Log("TV.Vinh User: " + userName + " has successful loged in");

    }

    void OnLoginError(BaseEvent evt)
    {
        Debug.Log("TV.Vinh Login error");
    }


    void OnLogout(BaseEvent evt)
    {
        Debug.Log("TV.Vinh User: user has loged out");
    }
    #endregion


    #region HandleUserInput
    void OnClickConnect()
    {
        if (!sfConnectObj.IsConnected)
        {
            Debug.Log("trying to connect...");
            sfConnectObj.Connect(ServerDefine.SERVER_NAME, ServerDefine.SERVER_PORT);
            // attemp to connect SF server per x seconds
            // InvokeRepeating("AttempToConnect", 2, 5);
            //Debug.Log("TV.Vinh " + sfConnectObj.CurrentIp);
            //Debug.Log("TV.Vinh " + sfConnectObj.CurrentPort);
        }
        //else {
        //    Debug.Log("TV.Vinh " + sfConnectObj.CurrentIp);
        //    Debug.Log("TV.Vinh " + sfConnectObj.CurrentPort);
        //}
    }

    void OnClickLogin()
    {
        if (sfConnectObj.IsConnected && sfConnectObj.MySelf == null)
        {
            userName = SystemInfo.deviceName;
            sfConnectObj.Send(new LoginRequest(userName, "", ServerDefine.ZONE));
        }
        else if (!sfConnectObj.IsConnected)
        {
            Debug.Log("TV.Vinh pls connect first"); 
        }
    }


    void OnClickLogout()
    {
        if (sfConnectObj.IsConnected && sfConnectObj.MySelf != null)
        {
            sfConnectObj.Send(new LogoutRequest());
        }
    }

    void OnClickJoinRoom() {
        if (sfConnectObj.MySelf != null) {
            IamReady(new SFSObject());
        }
    }

    //void OnClickJoinRoom() {
    //    if (sfConnectObj.MySelf == null)
    //    {
    //        Debug.Log("TV.Vinh pls login first");
    //    }
    //    else {
    //        if (sfConnectObj.LastJoinedRoom == null)
    //        {
    //            sfConnectObj.Send(new JoinRoomRequest("CZ1"));
    //        }
    //        else {
    //            Debug.Log("TV.Vinh last joined Room: " + sfConnectObj.LastJoinedRoom.Name);
    //            sfConnectObj.Send(new LeaveRoomRequest());
    //        }
    //    }
    //}

    #endregion

    #region HandleRequestToServer


    /// <summary>
    /// tell server find room, player & I'm ready to play
    /// </summary>
    /// <param name="info">extra info for server</param>
    void IamReady(SFSObject info) {
        sfConnectObj.Send(new ExtensionRequest(Commands.CMD_READY, info, sfConnectObj.LastJoinedRoom));
    }

    /// <summary>
    /// tell server I'd made a move
    /// </summary>
    /// <param name="info"></param>
    void MoveMade(SFSObject info) {
        sfConnectObj.Send(new ExtensionRequest(Commands.CMD_MOVE, info, sfConnectObj.LastJoinedRoom));
    }

    #endregion

    #region HandleResponseFromServer

    void OnExtensionResponse(BaseEvent evt) { 
        string cmd = evt.Params[MySFSParams.PARAM_CMD] as string;
        SFSObject dataObject = evt.Params[MySFSParams.PARAM_DATA] as SFSObject;

        switch (cmd) {

            // wait for another player
            case "wait":

                break;

            // enough players, let's start game
            case "start":
                
                break;
        
            // opponent move
            case "move":

                break;

            // win
            case "win":

                break;

            // lose
            case "lose":

                break;

            // draw
            case "tie":

                break;
        }
    }

    #endregion
}
